import sqlite3
import os
import hashlib
import time
from email.mime.text import MIMEText

class ActivationError(Exception):
  def __init__(self, reason):
    self.reason = reason
  def __str__(self):
    return repr(self.reason)

"""
Returns secure hash of password for db storage
"""
def hash_password(password):
  return hashlib.sha224(password.encode("ascii")).hexdigest()

"""
Returns user tuple if user exists, otherwise false
"""
def get_user(username, password):
  password = hash_password(password)
  conn = sqlite3.connect(os.environ["DOCUMENT_ROOT"] 
      + "/PictureShare/pygallery.sqlite")
  conn.row_factory = sqlite3.Row
  user_cur = conn.cursor()
  user_cur.execute("""
    select u.* from users u where u.username = ? and u.password = ?
    """, (username, password))
  user = user_cur.fetchone()
  user_cur.close()
  conn.close()
  return user

"""
Returns user tuple if user exists, otherwise false
"""
def get_user_by_name(username):
  conn = sqlite3.connect(os.environ["DOCUMENT_ROOT"] 
      + "/PictureShare/pygallery.sqlite")
  conn.row_factory = sqlite3.Row
  user_cur = conn.cursor()
  user_cur.execute("select u.* from users u where u.username = ?", \
      (username,))
  user = user_cur.fetchone()
  user_cur.close()
  conn.close()
  return user

"""
Returns user tuple if user exists, otherwise None
"""
def get_user_by_id(user_id):
  conn = sqlite3.connect(os.environ["DOCUMENT_ROOT"] 
      + "/PictureShare/pygallery.sqlite")
  conn.row_factory = sqlite3.Row
  user_cur = conn.cursor()
  user_cur.execute("select u.* from users u where u.user_id = ?", \
      (user_id,))
  user = user_cur.fetchone()
  user_cur.close()
  conn.close()
  return user

"""
Attempt to activate user account with activation_id
Throws ActivationError on failure
"""
def activate_user(activation_id):
  conn = sqlite3.connect(os.environ["DOCUMENT_ROOT"] 
      + "/PictureShare/pygallery.sqlite")
  conn.row_factory = sqlite3.Row
  cur = conn.cursor()
  # Try to find activation record
  cur.execute("""
  select a.* from user_activation a
  where activation_id = ?
  """, (activation_id,))
  record = cur.fetchone()
  if record is not None:
    # Delete record and set user to active
    cur.execute("""
    delete from user_activation
    where activation_id = ?
    """, (activation_id,))
    user_id = record["user_id"]
    cur.execute("""
    update users
    set activated = 1
    where user_id = ?
    """, (user_id,))
  else:
    raise ActivationError("activation_id not found")
  cur.close()
  conn.commit()
  conn.close()

"""
Create user
"""
def create_user(user):
  conn = sqlite3.connect(os.environ["DOCUMENT_ROOT"] 
      + "/PictureShare/pygallery.sqlite")
  conn.row_factory = sqlite3.Row
  user_cur = conn.cursor()
  user_cur.execute("""
  insert into users (user_id, username, password, activated)
  values (NULL, ?, ?, 0)
  """, (user["username"], user["password"]))
  # Send user activation email
  hash_str = str(time.time()) + user["username"]
  activation_id = hashlib.sha224(hash_str).hexdigest()
  message = 'Activate your account here:\n'
  message += 'http://sslab15.cs.purdue.edu:8399/activate.cgi?id='
  message += activation_id
  mailpipe = os.popen('mail -s "pygallery" %s' % user["username"], "w")
  mailpipe.write(message)
  # Save activation id in database
  user_cur.execute("""
  insert into user_activation (user_id, activation_id)
  values (?, ?)
  """, (user_cur.lastrowid, activation_id)) 
  user_cur.close()
  conn.commit()
  conn.close()

"""
Update user with new values
"""
def update_user(user):
  conn = sqlite3.connect(os.environ["DOCUMENT_ROOT"] 
      + "/PictureShare/pygallery.sqlite")
  conn.row_factory = sqlite3.Row
  user_cur = conn.cursor()
  user_cur.execute("""
  update users
  set password = ?,
      activated = ?
  where user_id = ?
  """, (user["password"], user["activated"], user["user_id"]))
  user_cur.close()
  conn.commit()
  conn.close()
